/*
 * $Id:
 *
 * Copyright (C) 2009 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN : utility
 *============================================================
 * abstract: This module provides utility functions
 * author  : SUG
 * history :
 *   1.0.0 090531 First Release
 *
 */

#ifndef _RR_UTIL_H_
#define _RR_UTIL_H_

#ifdef ANDROIDNDK
#include <sys/types.h>

#else // ANDROIDNDK

#ifndef __u_char_defined
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
#endif

#define	u_long		u_int
#endif // ANDROIDNDK

#ifndef NULL
#define NULL    0
#endif

/*
 *---------------------------------------------------------------------
 *
 * 標準メモリ制御関数ラッパー
 *
 *---------------------------------------------------------------------
 */

/* 動的メモリ獲得 */

void *rr_malloc(u_long size);
void *rr_calloc(u_long nmemb, u_long size);
void rr_free(void *ptr);

#if USE_THREAD
/*
 *---------------------------------------------------------------------
 *
 * MUTEX関数
 *
 *---------------------------------------------------------------------
 */

void *rr_mutex_init(void);
int rr_mutex_lock(void *mutex);
int rr_mutex_unlock(void *mutex);
int rr_mutex_destroy(void *mutex);

#endif /* USE_THREAD */

/*
 *---------------------------------------------------------------------
 *
 * キュー構造
 *
 *---------------------------------------------------------------------
 */

typedef struct rr_que_list rr_que_list_t;
typedef struct rr_que rr_que_t;

/* キューリスト構造体 */

struct rr_que_list
{
    rr_que_t    *next;
    rr_que_t    *prev;
    int         qlen;
};

/* キュー構造体 */
struct rr_que
{
    rr_que_t        *next;
    rr_que_t        *prev;
    rr_que_list_t   *list;
};

/* キュー初期化 */

void rr_que_init(rr_que_t *que);

/* キューリスト初期化 */

void rr_que_list_init(rr_que_list_t *list);

/* キューの先頭に接続 */

void rr_enque_head(rr_que_list_t *list, rr_que_t *newp);

/* キューの最後に接続 */

void rr_enque_tail(rr_que_list_t *list, rr_que_t *newp);

/* 指定位置の直前に接続 */

void rr_enque_before(rr_que_t *pos, rr_que_t *newp);

/* 指定位置の直後に接続 */

void rr_enque_after(rr_que_t *pos, rr_que_t *newp);

/* キューの先頭から取り出す */

rr_que_t *rr_deque_head(rr_que_list_t *list);

/* キューの最後から取り出す */

rr_que_t *rr_deque_tail(rr_que_list_t *list);

/* オフセットを指定してキューから取り出す */

rr_que_t *rr_deque_offset(rr_que_list_t *list, int off);

/* オフセットを指定してキューを参照する */

rr_que_t *rr_que_get_offset(rr_que_list_t *list, int off);

/* 指定のキューをリストから取り出す */

int rr_deque_que(rr_que_t *que);

/* MACRO */
#define _QUE_INIT(que) rr_que_init((rr_que_t *)que)
#define _QUE_LIST_INIT(list) rr_que_list_init((rr_que_list_t *)list)
#define _ENQUE_HEAD(list, newp) \
                rr_enque_head((rr_que_list_t *)list, (rr_que_t *)newp)
#define _ENQUE_TAIL(list, newp) \
                rr_enque_tail((rr_que_list_t *)list, (rr_que_t *)newp)
#define _DEQUE_HEAD(type, list) (type)rr_deque_head((rr_que_list_t *)list)
#define _DEQUE_TAIL(type, list) (type)rr_deque_tail((rr_que_list_t *)list)
#define _DEQUE_OFFSET(type, list, off) \
                (type)rr_deque_offset((rr_que_list_t *)list, off)
#define _DEQUE_QUE(que) rr_deque_que((rr_que_t *)que)
#define _QLEN(list) (list)->qlen

/*
 *---------------------------------------------------------------------
 *
 * 乱数
 *
 *---------------------------------------------------------------------
 */

/* 乱数種の設定 */

void rr_srand(u_int seed);

/* 乱数の生成 */

int rr_rand(void);

/*
 *---------------------------------------------------------------------
 *
 * 標準ライブラリラッパー
 *
 *---------------------------------------------------------------------
 */

int rr_atoi(char *nptr);

/* データ長を指定した atoi 関数 */

int rr_natoi(char *nptr, int len);

/* バイナリ数をストリングに変換した場合のストリング長の計算 */

int rr_itoa_len(int n);

/* バイナリ数をストリングに変換しバッファに格納 */

char *rr_itoa(int n, char *cp);

/* 標準ストリング関数のラッパー */

char *rr_strcpy(char *dest, char *src);
char *rr_strncpy(char *dest, char *src, int n);
char *rr_strchr(char *s, int c);
char *rr_strrchr(char *s, int c);
int   rr_strlen(char *s);
int   rr_strcmp(char *s1, char *s2);
int   rr_strncmp(char *s1, char *s2, int n);
int   rr_strcasecmp(char *s1, char *s2);
int   rr_strncasecmp(char *s1, char *s2, int n);
void *rr_memset(void *s, int c, int n);
void *rr_memcpy(void *dest, void *src, int n);

/* ストリングバッファ構造体 */

typedef struct rr_str
{
    char    *ptr;       // バッファポインタ
    int     len;        // ストリング長
    int     dynamic;    // 1: アロケートされたバッファ(要開放)
} rr_str_t;

/* 構造体初期化 */

void rr_str_init(rr_str_t *str);

/* ストリングバッファ獲得、開放、コピー */

char *rr_str_alloc(rr_str_t *str, int len);
void rr_str_free(rr_str_t *str);
char *rr_str_memcpy(rr_str_t *str, char *dest);
char *rr_str_alcpy(rr_str_t *str, char *ptr);
char *rr_str_alncpy(rr_str_t *str, char *ptr, int len);

/* 構造体コピー */

int rr_str_clone(rr_str_t *to, rr_str_t *from);

/* 構造体比較 */

int rr_str_scmp(rr_str_t *str1, rr_str_t *str2);
int rr_str_scasecmp(rr_str_t *str1, rr_str_t *str2);

/* ストリング比較 */

int rr_str_cmp(rr_str_t *str, char *ptr);
int rr_str_ncmp(rr_str_t *str, char *ptr, int len);
int rr_str_casecmp(rr_str_t *str, char *ptr);
int rr_str_ncasecmp(rr_str_t *str, char *ptr, int len);

/* MACRO */

#define rr_str_set(a, b, c) { (a)->ptr = (b); (a)->len = (c); }

/* 時刻の取得 */

typedef struct rr_timeval
{
    long    tv_sec;             /* seconds */
    long    tv_usec;            /* microseconds */
} rr_timeval_t;

int rr_gettimeofday(rr_timeval_t *tv);

#endif /* _RR_UTIL_H_ */
